package com.cooper.mediadb.online;

import java.util.HashMap;
import android.content.Context;
import android.util.Log;

import com.cooper.scraper.DownloadException;
import com.cooper.scraper.DownloadParams;
import com.cooper.scraper.ResourceCollector;
import com.cooper.scraper.ResourceScraper;
import com.cooper.scraper.ResourceScraperRunner;
import com.cooper.scraper.ResultUrl;
import com.cooper.scraper.RunnerThread;
import com.cooper.scraper.ScraperException;
import com.cooper.scraper.ScraperPublishRunner;

public final class OnlineMediaScrapeRunner extends ScraperPublishRunner
		implements ResourceScraperRunner<OnlineMedia> {

	private static OnlineMediaScrapeRunner instance = null;

	public static void initConfigure(DownloadParams params) {
		instance = new OnlineMediaScrapeRunner(params);
	}

	public static OnlineMediaScrapeRunner getInstance() {
		if (instance == null) {
			instance = new OnlineMediaScrapeRunner();
		}
		return instance;
	}

	public static void destroyInstance() {
		if (instance != null) {
			instance.destroy();
			instance = null;
		}
	}

	private OnlineMediaScrapeRunner(DownloadParams params) {
		super(params);
	}

	private OnlineMediaScrapeRunner() {
		super();
	}

	@Override
	public void getBrowseParams(Context context, String scraperId) {
		run(ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX + scraperId,
				new DownloadBrowseParams(context, params, scraperId));
	}

	class DownloadBrowseParams extends RunnerThread {

		private Context context;
		private String scraperId;

		public DownloadBrowseParams(Context context, DownloadParams params,
				String scraperId) {
			super(params);
			this.context = context;
			this.scraperId = scraperId;
		}

		@Override
		public void run() {
			super.run();
			try {
				ResourceScraper<OnlineMedia> scraper = getOnlineMediaScraper(
						context, scraperId);

				complete(ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX
						+ scraperId, scraper.getBrowseUrlParams());
			} catch (ScraperException e) {
				Log.e("OnlineMediaScrapeRuner", e.getMessage(), e);
				fail(ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX
						+ scraperId, e.getErrorCode());
			} catch (Exception e) {
				Log.e("OnlineMediaScrapeRuner", e.getMessage(), e);
				fail(ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX
						+ scraperId, DownloadException.ERROR_OTHER);
			}

		}

	}

	@Override
	public void listResource(Context context,
			ResourceCollector<OnlineMedia> resultMedia) {
		if (resultMedia.ready()) {
			run(resultMedia.generateKey(), new DownloadResultMedia(params,
					resultMedia));
		} else {
			run(resultMedia.generateKey(), new RunDownloadResultMedia(context,
					params, resultMedia));
		}
	}

	class RunDownloadResultMedia extends RunnerThread {

		private ResourceCollector<OnlineMedia> resultMedias;
		private Context context;

		public RunDownloadResultMedia(Context context, DownloadParams params,
				ResourceCollector<OnlineMedia> resultMedias) {
			super(params);
			this.context = context;
			this.resultMedias = resultMedias;
		}

		@Override
		public void run() {
			super.run();
			if (!resultMedias.ready()) {
				try {
					OnlineMediaScraper scraper = getOnlineMediaScraper(context,
							resultMedias.getScraperId());
					resultMedias.setScraper(scraper,
							scraper.getBrowseUrlParams());

					OnlineMediaScrapeRunner.this.run(
							resultMedias.generateKey(),
							new DownloadResultMedia(params, resultMedias));
				} catch (ScraperException e) {
					fail(resultMedias.generateKey(), e.getErrorCode());
				} catch (Exception e) {
					fail(resultMedias.generateKey(),
							DownloadException.ERROR_OTHER);
				}

			}

		}
	}

	class DownloadResultMedia extends RunnerThread {

		private ResourceCollector<OnlineMedia> resultMedias;

		public DownloadResultMedia(DownloadParams params,
				ResourceCollector<OnlineMedia> resultMedias) {
			super(params);
			this.resultMedias = resultMedias;
		}

		@Override
		public void run() {
			super.run();
			try {
				if (!resultMedias.ready()) {
					return;
				}

				ResultUrl resultUrl = resultMedias.scraperListUrl();

				ResultUrl pageCountUrl = resultMedias.scraperPageCountUrl();

				boolean samePageCountPage = (pageCountUrl == null)
						|| pageCountUrl.equals(resultUrl);

				String redirectUrl = httpDownload.getRedirectUrl(resultUrl
						.getUrl());

				boolean redirect = false;
				if (!redirectUrl.equals(resultUrl.getUrl())) {
					resultUrl.setUrl(redirectUrl);
					redirect = true;
				}

				String page = httpDownload.downloadPage(resultUrl.getUrl(),
						resultUrl.getEncodingType(), false);
				if (!Thread.currentThread().isInterrupted()) {
					if (redirect) {
						resultMedias.scraperResult(page, resultUrl.getUrl(),
								redirectUrl);
					} else
						resultMedias.scraperResult(page, resultUrl.getUrl());

					if (!samePageCountPage) {
						redirect = false;
						redirectUrl = httpDownload.getRedirectUrl(pageCountUrl
								.getUrl());

						if (!redirectUrl.equals(pageCountUrl.getUrl())) {
							pageCountUrl.setUrl(redirectUrl);
							redirect = true;
						}
						page = httpDownload.downloadPage(pageCountUrl.getUrl(),
								pageCountUrl.getEncodingType());
					}

					if (redirect) {
						resultMedias.scraperPageCount(page);
					} else {
						resultMedias.scraperPageCount(page, redirectUrl);
					}

				}
				complete(resultMedias.generateKey(), resultMedias);
			} catch (DownloadException e) {
				fail(resultMedias.generateKey(), e.getErrorCode());
			} catch (ScraperException e) {
				fail(resultMedias.generateKey(), e.getErrorCode());
			} catch (Exception e) {
				Log.e("DownloadResultMovies.run", "result:" + resultMedias
						+ "resultUrl:", e);
				fail(resultMedias.generateKey(), DownloadException.ERROR_OTHER);
			}

		}
	}

	public void getResourceDetails(Context context, String scraperId,
			OnlineMedia media) {
		run(media.generateSubscribedKey(), new DownloadMediaDetails(context,
				params, scraperId, media));
	}

	class DownloadMediaDetails extends RunnerThread {

		private OnlineMedia movie;

		// private ResourceScraper<OnlineMedia> scraper;
		private String scraperId;
		private Context context;

		public DownloadMediaDetails(Context context, DownloadParams params,
				String scraperId, OnlineMedia movie) {
			super(params);
			this.scraperId = scraperId;
			this.movie = movie;
			this.context = context;
		}

		@Override
		public void run() {
			super.run();
			try {
				ResourceScraper<OnlineMedia> scraper = getOnlineMediaScraper(
						context, scraperId);

				String page = httpDownload.downloadPage(movie.getDetailsUrl(),
						movie.getDetailsPageEncodeType());
				complete(movie.generateSubscribedKey(),
						scraper.extractDetails(page, movie.getId()));
			} catch (DownloadException e) {
				fail(movie.generateSubscribedKey(), e.getErrorCode());
			} catch (ScraperException e) {
				fail(movie.generateSubscribedKey(), e.getErrorCode());
			} catch (Exception e) {
				Log.e("DownloadMediaDetails.run", "scraper:" + scraperId
						+ "result:" + movie.getTitle() + "resultUrl:", e);
				fail(movie.generateSubscribedKey(),
						DownloadException.ERROR_OTHER);
			}
		}
	}

	public void analyzeMediaUrl(Context context, MediaSource sources,
			String format) {
		run(sources.getUrl(), new AnalyzeVideoThread(params, sources, format));
	}

	private synchronized OnlineMediaScraper getOnlineMediaScraper(
			Context context, String scraperId) throws ScraperException {
		// TODO scraper params
		return new OnlineMediaScraper(scraperId,
				getScraper(context, scraperId), new HashMap<String, String>(0),
				params);
	}

}
